﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DBSourceToolsLib.CodeParser
{
    public abstract class BraceNode : IBraceChain
    {
        //private bool m_bHasLink;
        //protected ChainNode m_Chain;
        //public ChainNode()
        //{
        //    m_bHasLink = false;
        //}

        //public abstract void sendToChain(List<ParseObject> lstParseObjects, List<IResolved> lstResolved);

        //public void addToChain(ChainNode oChain)
        //{
        //    m_Chain = oChain;
        //    m_bHasLink = true;
        //}
        //public ChainNode getChain()
        //{
        //    return m_Chain;
        //}
        //public bool hasChain() { return m_bHasLink; }

        //protected void sendChain(List<ParseObject> lstParseObjects, List<IResolved> lstResolved)
        //{ // send the message on down the chain
        //    if (m_Chain != null)
        //        m_Chain.sendToChain(lstParseObjects, lstResolved);
        //}

        private BraceNode nextChain;
        //protected List<ParseObject> lstParseObjects;
        protected SourceFile m_SourceFile;
        private bool hasChain;

        public BraceNode()
        {
            hasChain = false;
        }

        public void addToChain(BraceNode c)
        {
            nextChain = c;
            hasChain = true;
        }

        public abstract bool interpret();

        public void sendtoChain(ref SourceFile oSourceFile)
        {
            m_SourceFile = oSourceFile;
            interpret();
            if (hasChain)
                nextChain.sendtoChain(ref oSourceFile);
        }

        public BraceNode getChainNode()
        {
            return nextChain;
        }

        public MatchParms MatchStartAndEndBrace(params int[] arrBraceTypes)
        {
            MatchParms oMatchParms = new MatchParms();

            bool bValid = false;
            int iQuoteType = -1;

            bool bFound = false;
            for (int iLineIx = 0; iLineIx < m_SourceFile.LineCount; iLineIx++)
            {
                SourceLine oSourceLine = m_SourceFile.ElementAt(iLineIx);

                for (int i = 0; i < oSourceLine.WordCount; i++)
                {
                    ParseObject oParseObject = oSourceLine.elementAt(i);
                    if (IsQuote(oParseObject, arrBraceTypes)) {
                        oMatchParms.iFirstLine = oParseObject.LineIdx;
                        oMatchParms.iFirstIdx = oParseObject.WordIdx;
                        iQuoteType = oParseObject.Value;
                        bFound = true;
                        break;
                    }
                        
                }
                if (bFound)
                    break;
            }

            bFound = false;            
            if (iQuoteType > 0)
            {
                for (int iLineIx = m_SourceFile.LineCount - 1; iLineIx > -1; iLineIx--)
                {
                    SourceLine oSourceLine = m_SourceFile.ElementAt(iLineIx);
                    for (int i = oSourceLine.WordCount -1 ; i > -1; i--)
                    {
                        ParseObject oParseObject = oSourceLine.elementAt(i);
                        if (IsQuote(oParseObject, GetOpposingBraceType( iQuoteType)))
                        {
                            oMatchParms.iSecondLine = oParseObject.LineIdx;
                            oMatchParms.iSecondIdx = oParseObject.WordIdx;
                            iQuoteType = oParseObject.Value;
                            bFound = true;
                            break;
                        }
                    }
                    if (bFound)
                        break;
                }

            }

            if ((oMatchParms.iFirstLine == oMatchParms.iSecondLine)
                && oMatchParms.iFirstIdx == oMatchParms.iSecondIdx)
            {
                oMatchParms.iSecondLine = -1;
                oMatchParms.iSecondIdx = -1;
            }
            return oMatchParms;

        }

        private bool IsQuote(ParseObject parseObject, params int[] matchQuoteTypes)
        {
            if (parseObject.ParseType == ParseObject.BRACE)
            {
                if (matchQuoteTypes.Length > 0)
                {
                    for (int i = 0; i < matchQuoteTypes.Length; i++)
                        if (parseObject.Value == matchQuoteTypes[i])
                            return true;
                }
                else
                    return true;
            }
            return false;
        }

        private int GetOpposingBraceType(int iQuoteType)
        {
            switch (iQuoteType)
            {
                case ParseBrace.BRACE_START:
                    return ParseBrace.BRACE_END;
                case ParseBrace.BRACKET_START:
                    return ParseBrace.BRACKET_END;
                default:
                    return iQuoteType;
            }

        }

        public bool HasUnresolvedBraces(params int[] arrBraceTypes)
        {
            for (int iLineIx = 0; iLineIx < m_SourceFile.LineCount; iLineIx++)
            {
                SourceLine oSourceLine = m_SourceFile.ElementAt(iLineIx);
                for (int i = 0; i < oSourceLine.WordCount; i++)
                {
                    ParseObject oParseObject = oSourceLine.elementAt(i);
                    foreach (int iBraceType in arrBraceTypes)
                    {
                        if (oParseObject.Value == iBraceType
                            && !oParseObject.IsResolved)
                            return true;
                    }
                }
            }
            return false;
        }

        public void MatchNextBrace(params int[] arrBraceTypes)
        {
            MatchParms oMatchParms = MatchStartAndEndBrace(arrBraceTypes);
            if (oMatchParms.iFirstLine > -1)
            {
                ParseBrace oFirstBrace = (ParseBrace)m_SourceFile.ElementAt(oMatchParms.iFirstLine).elementAt(oMatchParms.iFirstIdx);
                oFirstBrace.IsResolved = true;
                oFirstBrace.SetIsStartBrace();
                oFirstBrace.SetPartner(oMatchParms.iSecondLine, oMatchParms.iSecondIdx);
            }

            if (oMatchParms.iSecondLine > -1)
            {
                ParseBrace oFirstBrace = (ParseBrace)m_SourceFile.ElementAt(oMatchParms.iSecondLine).elementAt(oMatchParms.iSecondIdx);
                oFirstBrace.IsResolved = true;
                oFirstBrace.SetPartner(oMatchParms.iFirstLine, oMatchParms.iFirstIdx);
            }
            else
            {
                string strError = String.Format("Unmatched Quote : Line {0}", oMatchParms.iFirstLine);
                m_SourceFile.ElementAt(oMatchParms.iFirstLine).SetError(strError);
            }
        }




    }

    public class MatchParms {
        public int iFirstLine = -1;
        public int iFirstIdx = -1;
        public int iSecondLine = -1;
        public int iSecondIdx = -1;
    }
}
